package datetime

import (
	"errors"
	"fmt"
	"strings"
	"time"
)

// SplitStr2DateRange 将包含分隔符的日期字符串拆分为开始和结束时间。
//
// 参数:
//   - utime: 包含分隔符的日期字符串(如"2023-01-01~2023-01-02")
//   - separator: 分隔符(如"~")
//
// 返回值:
//   - start: 开始时间字符串(格式为"YYYY-MM-DD 00:00:00")
//   - end: 结束时间字符串(格式为"YYYY-MM-DD 23:59:59")
//   - err: 如果格式错误则返回错误
//
// 示例:
//
//	start, end, err := SplitStr2DateRange("2023-01-01~2023-01-02", "~")
//	// 返回 "2023-01-01 00:00:00", "2023-01-02 23:59:59", nil
func SplitStr2DateRange(utime, separator string) (start string, end string, err error) {
	dateArray := strings.Split(separator, utime)
	if len(dateArray) != 2 {
		err = errors.New("time '" + utime + "' format error, have no '" + separator + "'")
		return
	}
	start = dateArray[0] + " 00:00:00"
	end = dateArray[1] + " 23:59:59"

	return
}

// Timestamp2TimeInt64 将int64类型的时间戳转换为time.Time。
//
// 参数:
//   - in: Unix时间戳(秒)
//
// 返回值:
//   - time.Time: 转换后的时间
//
// 示例:
//
//	t := Timestamp2TimeInt64(1672531200) // 返回2023-01-01 00:00:00 +0000 UTC
func Timestamp2TimeInt64(in int64) time.Time {
	return time.Unix(in, 0)
}

// Timestamp2TimeUint64 将uint64类型的时间戳转换为time.Time。
//
// 参数:
//   - in: Unix时间戳(秒)
//
// 返回值:
//   - time.Time: 转换后的时间
//
// 示例:
//
//	t := Timestamp2TimeUint64(1672531200) // 返回2023-01-01 00:00:00 +0000 UTC
func Timestamp2TimeUint64(in uint64) time.Time {
	return time.Unix(int64(in), 0)
}

// FormatYDMHMS 将时间格式化为"YYYY-MM-DD HH:MM:SS"格式的字符串。
//
// 参数:
//   - in: 要格式化的时间
//
// 返回值:
//   - string: 格式化后的时间字符串
//
// 示例:
//
//	str := FormatYDMHMS(time.Now()) // 返回如"2023-01-01 12:00:00"
func FormatYDMHMS(in time.Time) string {
	return in.Format(TimeFormatYMDhms)
}

// NowStrYMDHMS 返回当前时间的"YYYY-MM-DD HH:MM:SS"格式字符串。
//
// 返回值:
//   - string: 当前时间的格式化字符串
//
// 示例:
//
//	str := NowStrYMDHMS() // 返回如"2023-01-01 12:00:00"
func NowStrYMDHMS() string {
	return FormatYDMHMS(time.Now())
}

// DayStartTime 返回给定时间当天的开始时间(00:00:00)。
//
// 参数:
//   - t: 输入时间
//
// 返回值:
//   - time.Time: 当天的开始时间
//
// 示例:
//
//	start := DayStartTime(time.Now()) // 返回今天00:00:00的时间
func DayStartTime(t time.Time) time.Time {
	return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location())
}

// YesterdayStartTime 返回昨天开始时间(00:00:00)。
//
// 返回值:
//   - time.Time: 昨天00:00:00的时间
//
// 示例:
//
//	yesterday := YesterdayStartTime() // 返回昨天00:00:00的时间
func YesterdayStartTime() time.Time {
	now := time.Now()
	mm, _ := time.ParseDuration("-24h")
	return DayStartTime(now.Add(mm))
}

// TodayStartTime 返回今天开始时间(00:00:00)。
//
// 返回值:
//   - time.Time: 今天00:00:00的时间
//
// 示例:
//
//	today := TodayStartTime() // 返回今天00:00:00的时间
func TodayStartTime() time.Time {
	return DayStartTime(time.Now())
}

// TomorrowStartTime 返回明天开始时间(00:00:00)。
//
// 返回值:
//   - time.Time: 明天00:00:00的时间
//
// 示例:
//
//	tomorrow := TomorrowStartTime() // 返回明天00:00:00的时间
func TomorrowStartTime() time.Time {
	now := time.Now()
	mm, _ := time.ParseDuration("24h")
	return DayStartTime(now.Add(mm))
}

// LastDay 返回给定时间的前一天同一时间。
//
// 参数:
//   - d: 输入时间
//
// 返回值:
//   - time.Time: 前一天同一时间
//
// 示例:
//
//	lastDay := LastDay(time.Now()) // 返回昨天此时的时间
func LastDay(d time.Time) time.Time {
	duration1Day, _ := time.ParseDuration("-24h")
	return d.Add(duration1Day)
}

// NextDay 返回给定时间的后一天同一时间。
//
// 参数:
//   - d: 输入时间
//
// 返回值:
//   - time.Time: 后一天同一时间
//
// 示例:
//
//	nextDay := NextDay(time.Now()) // 返回明天此时的时间
func NextDay(d time.Time) time.Time {
	duration1Day, _ := time.ParseDuration("+24h")
	return d.Add(duration1Day)
}

// EmptyTimeToNow 如果输入时间为零值，则返回当前时间，否则返回原时间。
//
// 参数:
//   - t: 输入时间
//
// 返回值:
//   - time.Time: 处理后的时间
//
// 示例:
//
//	validTime := EmptyTimeToNow(time.Time{}) // 返回当前时间
//	validTime := EmptyTimeToNow(someTime) // 返回someTime
func EmptyTimeToNow(t time.Time) time.Time {
	if t.IsZero() {
		return time.Now()
	}
	return t
}

// FormatAsDate 将时间格式化为"YYYY-MM-DD"格式字符串。
//
// 参数:
//   - t: 输入时间
//
// 返回值:
//   - string: 格式化后的日期字符串
//
// 示例:
//
//	dateStr := FormatAsDate(time.Now()) // 返回如"2023-01-01"
func FormatAsDate(t time.Time) string {
	year, month, day := t.Date()
	return fmt.Sprintf("%d-%02d-%02d", year, month, day)
}

// TimeFormatByYMDHMS 将常见日期时间格式转换为Go标准格式。
// 支持转换的格式标记：
//   - yyyy → 2006 (年)
//   - MM → 01 (月)
//   - dd → 02 (日)
//   - hh → 15 (时)
//   - mm → 04 (分)
//   - ss → 05 (秒)
//   - .sss → .000 (毫秒)
//
// 参数:
//   - format: 输入格式字符串(如"yyyy-MM-dd hh:mm:ss")
//
// 返回值:
//   - string: 转换后的Go标准格式字符串
//
// 示例:
//
//	goFormat := TimeFormatByYMDHMS("yyyy-MM-dd hh:mm:ss") // 返回"2006-01-02 15:04:05"
func TimeFormatByYMDHMS(format string) (res string) {
	format = strings.Replace(format, "yyyy", "2006", -1) // year
	format = strings.Replace(format, "MM", "01", -1)     // month
	format = strings.Replace(format, "dd", "02", -1)     // day
	format = strings.Replace(format, "hh", "15", -1)     // hour
	format = strings.Replace(format, "mm", "04", -1)     // minute
	format = strings.Replace(format, "ss", "05", -1)     // second
	format = strings.Replace(format, ".sss", ".000", -1) // millisecond

	return format
}

// TimeFormat 按指定格式格式化时间。
// 先使用TimeFormatByYMDHMS转换格式字符串，再格式化时间。
//
// 参数:
//   - tm: 要格式化的时间
//   - format: 格式字符串(如"yyyy-MM-dd hh:mm:ss")
//
// 返回值:
//   - string: 格式化后的时间字符串
//
// 示例:
//
//	str := TimeFormat(time.Now(), "yyyy-MM-dd") // 返回如"2023-01-01"
func TimeFormat(tm time.Time, format string) (res string) {
	return tm.Format(TimeFormatByYMDHMS(format))
}

// Time2Pointer 将time.Time转换为指针类型。
// 这是一个解决Go中时间指针转换问题的实现，参考Go官方issue #45653。
//
// 参数:
//   - input: 输入时间
//
// 返回值:
//   - *time.Time: 时间指针
//
// 示例:
//
//	timePtr := Time2Pointer(time.Now()) // 返回当前时间的指针
func Time2Pointer(input time.Time) *time.Time {
	return &(&struct{ time.Time }{input}).Time
}
